from _weakref import ref



class WeakDict(object):
	__slots__ = ["_deller", "_dict", "_mapping", "__weakref__"]
	def __init__(self):
		self._dict = {}
		self._mapping = {}
		def deller(pobj, selfref = ref(self)):
			s = selfref()
			if s is not None:
				dummy = lambda: None
				s._dict.pop(s._mapping.pop(id(pobj), dummy), dummy)
		self._deller = deller
	def __repr__(self):
		return repr(self._dict)
	def __len__(self):
		return len(self._dict)
	def __contains__(self, key):
		return self._dict.get(key, lambda: None)() is not None
	def get(self, key, default = None):
		try:
			return self[key]
		except KeyError:
			return default
	def __getitem__(self, key):
		obj = self._dict[key]()
		if obj is None:
			raise KeyError(key)
		return obj
	def __delitem__(self, key):
		del self._mapping[id(self._dict.pop(key))]
	def __setitem__(self, key, value):
		if key in self._dict:
			del self._mapping[id(self._dict.pop(key))]
		pobj = ref(value, self._deller)
		self._dict[key] = pobj
		self._mapping[id(pobj)] = key


class WeakSet(object):
	__slots__ = ["_deller", "_set", "__weakref__"]
	def __init__(self):
		self._set = set()
		def deller(pobj, selfref = ref(self)):
			s = selfref()
			if s is not None:
				s._set.discard(pobj)
		self._deller = deller
	def __repr__(self):
		return repr(self._set)
	def __len__(self):
		return len(self._set)
	def __contains__(self, obj):
		return ref(obj) in self._set
	def __iter__(self):
		for obj in self._set:
			o = obj()
			if o is not None:
				yield obj()
	def add(self, obj):
		self._set.add(ref(obj, self._deller))
	def remove(self, obj):
		self._set.remove(ref(obj))










